<template>
  <div class="v-date-picker" ref="datePickerObj">
    <!-- <div class="v-date-picker-header">
      <a href="javascript:;" class="iconfont icon-arrow-right-line v-date-picker-header__prev" @click="prevOrNextDateChange(-1)"></a>
      <span class="v-date-picker-header__label" @click="showDropList=!showDropList">
        <template v-if="dateValue.length>1">
         {{dateValueStr}}
        </template>
      </span>
      <a href="javascript:;" class="iconfont icon-arrow-right-line v-date-picker-header__next" @click="prevOrNextDateChange(1)"></a>
    </div> -->
    <div class="v-date-picker-droplist" ref="droplistBox" :style="{top:droplistTop+'px'}" @click="showDropList=false">
      <div class="v-date-picker-droplist-header" @click.stop="showDropList=true">
        <div class="v-date-picker-droplist-yearhandler">
          <a href="javascript:;" class="iconfont icon-arrow-right-line v-date-picker-header__prev" @click="yearChangeHandler(-1)"></a>
          {{selYear}}
          <a href="javascript:;" class="iconfont icon-arrow-right-line v-date-picker-header__next" @click="yearChangeHandler(1)"></a>
        </div>
        <div class="v-date-picker-droplist-monthhandler" ref="monthList">
          <a href="javascript:;" class="month-item" v-for="(item,index) in monthList" :key="index" :class="[{active:+selMonth===index},{disabled:!checkMonthEnable(index)}]" @click="monthChangeHandler(index)">{{item}}</a>
        </div>
      </div>
      <div class="v-date-picker-droplist-content" @click.stop="showDropList=true">
        <ul class="calendar-row calendar-row-header">
          <li class="week-value" v-if="showWeek"></li>
          <li v-for="(item,index) in weekList" :key="index">{{item}}</li>
        </ul>
        <ul class="calendar-row calendar-row-body" v-for="(item,index) in calendayArr" :key="index">
          <li class="week-value" v-if="showWeek">{{item.weekVal[1]}}周</li>
          <li class="day-cell" v-for="(item1,index1) in item.dayList" :key="index1" 
          :class="[
          {disabled:(index===0 && item1.dateNum > 10) || (index>2 && item1.dateNum < 10) || !checkDateEnable(item1.date)},
          {active:item1.dateStr === dateValueStr},{selected:selectDays.includes(item1.dateStr2)}]"
           @click.stop="dateChangeHandler(item1)"
          >
            <span class="date-num">
              <template v-if="isToday(item1.date)">
              今
            </template>
            <template v-else>
              {{item1.dateNum}}
            </template>
            </span>
          </li>
        </ul>
      </div>
    </div>
  </div>
</template>

<script>
/*
   功能模块  日期选择器
   创建人    zgf
   更新时间  2019/12/25
   页面参数  
   备注      
*/
import DateUtil from './dateUtil.js'
export default {
  name: 'VDatePicker',
  props: {
    value: {
      type: String,
      default:''
    },
    maxDate: {
      type: String,
      default:''
    },
    maxMsg:{
      type:String,
      default:''
    },
    minDate: {
      type: String,
      default:''
    },
    minMsg:{
      type:String,
      default:''
    },
    showWeek:{
      type:Boolean,
      default:false
    },
    selectDays:{
      type:Array,
      default(){
        return []
      }
    }
  },
  data() {
    return {
      todayDate: new Date().getDate(),
      droplistTop: 0,
      showDropList: true,
      dateValue: [],
      selYear: 2019,
      selMonth: 10,
      monthList: [
        '1月',
        '2月',
        '3月',
        '4月',
        '5月',
        '6月',
        '7月',
        '8月',
        '9月',
        '10月',
        '11月',
        '12月'
      ],
      weekList: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
      calendayArr: []
    }
  },
  computed: {
    dateValueStr(){
      return DateUtil.formatDate(this.dateValue,'yyyy年MM月dd日')
    },
    scroller() {
      return DateUtil.getScrollEventTarget(this.$el);
    }
  },
  watch: {
    value: {
      deep: true,
      handler(newVal) {
        this.dateValue = newVal
        this.calendarRender()
      }
    },
    dateValue: {
      deep: true,
      handler(newVal) {
        this.$emit('input', newVal)
      }
    },
    selMonth(newVal) {
      this.$refs.monthList.scrollLeft = 44 * newVal - 100
    },
    showDropList(newVal) {
      if (newVal) {
        this.$nextTick(() => {
          this.$refs.monthList.scrollLeft = 44 * this.selMonth - 100
          // this.updateOffsetTop()
        })
      this.scroller.addEventListener('scroll',this.onScroll)
      }else{
        this.scroller.removeEventListener('scroll',this.onScroll)
      }
    }
  },
  mounted() {
    this.setDefaultVal()
    this.yearAndMonthRender()
    document.addEventListener('click',(e)=>{
      let ignNames = ['v-date-picker-header','v-date-picker-header__label','iconfont icon-arrow-right-line v-date-picker-header__next','iconfont icon-arrow-right-line v-date-picker-header__prev']
      if(ignNames.indexOf(e.target.className)!==-1){
        return false
      }
      this.showDropList = false
    })
  },
  methods: {
    //判断某日期是否是今天
    isToday(date){
      let nowStr = DateUtil.formatDate(new Date(),'yyyyMMdd')
      let dateStr = DateUtil.formatDate(date,'yyyyMMdd')
      return nowStr === dateStr
    },
    //计算top值
    updateOffsetTop(){
      let rect = this.$refs.datePickerObj.getBoundingClientRect()
      this.droplistTop = rect.y ? rect.y + rect.height : rect.top + rect.height
    },
    //滚动时重新计算top值
    onScroll(){
      // this.updateOffsetTop()
    },
    //字符串日期转换成数组形式
    dateStrToArr(dateStr){
      if(dateStr===''){
        dateStr = new Date()
      }else{
        dateStr = new Date(DateUtil.formatDate(dateStr,'yyyy/MM/dd'))
      }
      let y = dateStr.getFullYear()
      let m = dateStr.getMonth()+1
      let d = dateStr.getDate()
      return [y,m,d]
    },
    //输入值如果为空，默认当前周
    setDefaultVal() {
      this.dateValue = this.value
      if (this.value) {
        this.dateValue = DateUtil.formatDate(new Date(),'yyyy/MM/dd')
        let dateValueArr = this.dateStrToArr(this.dateValue)
        this.selYear = dateValueArr[0]
        this.selMonth = dateValueArr[1]-1
        this.calendarRender()
      }
    },
    //设置选择的月份和年份
    setYearAndMonth(year,month){
      this.selYear = year
      this.selMonth = month - 1
      this.calendarRender()
    },
    //年月条条渲染
    yearAndMonthRender() {},
    //日历列表渲染
    calendarRender() {
      let dayOneDateObj = new Date(
        this.selYear + '/' + (+this.selMonth + 1) + '/1'
      )
      let firstDay = dayOneDateObj.getDay()
      firstDay = firstDay === 0 ? 7 : firstDay
      let begin = dayOneDateObj.getTime() - (firstDay - 1) * 60 * 60 * 1000 * 24
      let month2 = DateUtil.isLeapYear(this.selYear) ? 29 : 28 //2月平年28天，闰年29天
      let lastDayArr = [31, month2, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
      let lastDayObj = new Date(
        this.selYear +
          '/' +
          (+this.selMonth + 1) +
          '/' +
          lastDayArr[this.selMonth]
      )
      let lastDayWeek = lastDayObj.getDay()
      lastDayWeek = lastDayWeek === 0 ? 7 : lastDayWeek
      let end = lastDayObj.getTime() + (7 - lastDayWeek) * 60 * 60 * 1000 * 24
      let oneWeek = 7 * 24 * 60 * 60 * 1000
      let oneDay = 1 * 24 * 60 * 60 * 1000
      let calendayArr = []
      for (var i = begin; i < end; i += oneWeek) {
        let l = i + 6 * 24 * 60 * 60 * 1000
        let weekDaysArr = []
        for (var j = i; j <= l; j += oneDay) {
          let dd = new Date(j)
          weekDaysArr.push({
            dateNum: dd.getDate(),
            date: dd,
            dateStr: DateUtil.formatDate(dd,'yyyy年MM月dd日'),
            dateStr2: DateUtil.formatDate(dd,'yyyy-MM-dd'),
          })
        }
        calendayArr.push({
          weekVal: DateUtil.getWeekByDate(new Date(i)),
          dayList: weekDaysArr
        })
      }
      this.calendayArr = calendayArr
    },
    //前一天，后一天 切换
    prevOrNextDateChange(step) {
      let oneDay = 1 * 24 * 60 * 60 * 1000
      let curSelectDateTime = new Date(DateUtil.formatDate(this.dateValue,'yyyy/MM/dd')).getTime()
      let resultDate = null
      if (step < 0) {
        //前一天
        resultDate = new Date(curSelectDateTime - oneDay)
      } else {
        //后一天
        resultDate = new Date(curSelectDateTime + oneDay)
      }
      if(!this.checkDateEnable(resultDate,true)){
        return
      }
      this.selMonth = resultDate.getMonth()
      this.selYear = resultDate.getFullYear()
      this.dateValue = DateUtil.formatDate(resultDate,'yyyy/MM/dd')
      this.$emit('change', this.dateValue)
      // this.showDropList = false
    },
    //年改变
    yearChangeHandler(step) {
      if(!this.checkYearEnable(this.selYear+step)){
        return false
      }
      this.selYear += step
      this.calendarRender()
      this.$emit('monthChange',[this.selYear,this.selMonth+1])
    },
    //月改变
    monthChangeHandler(index) {
      if (!this.checkMonthEnable(index,true)) {
        return false
      }
      this.selMonth = index
      this.calendarRender()
      this.$emit('monthChange',[this.selYear,this.selMonth+1])
    },
    //日期改变
    dateChangeHandler(item) {
      if(!this.checkDateEnable(item.date,true)){
        return
      }
      this.showDropList = false
      let arr = this.dateStrToArr(item.date)
      this.selYear = arr[0]
      this.selMonth = arr[1]-1
      this.dateValue = DateUtil.formatDate(item.date,'yyyy/MM/dd')
      this.$emit('change', this.dateValue)
    },
    //检查年是否超出范围
    checkYearEnable(year) {
      if (this.maxDate) {
        let maxYear = new Date(DateUtil.formatDate(this.maxDate,'yyyy/MM/dd')).getFullYear()
        if(year > maxYear){
          if(this.maxMsg) this.$toast(this.maxMsg)
          return false
        }
      }
      if (this.minDate) {
        let minYear = new Date(DateUtil.formatDate(this.minDate,'yyyy/MM/dd')).getFullYear()
        if(year < minYear){
          if(this.minMsg) this.$toast(this.minMsg)
          return false
        }
      }
      return true
    },
    //检查日期是否超出范围
    checkDateEnable(dateVal,showMsg) {
      let curStr = DateUtil.formatDate(dateVal,'yyyyMMdd')
      if (this.maxDate) {
        let maxStr = DateUtil.formatDate(this.maxDate,'yyyyMMdd')
        if(+curStr > +maxStr){
          if(this.maxMsg && showMsg) this.$toast(this.maxMsg)
          return false
        }
      }
      if (this.minDate) {
        let minStr = DateUtil.formatDate(this.minDate,'yyyyMMdd')
        if(+curStr < +minStr){
          if(this.minMsg && showMsg) this.$toast(this.minMsg)
          return false
        }
      }
      return true
    },
    //检查月是否超出范围
    checkMonthEnable(index,showMsg) {
      if (this.maxDate) {
        let maxDate = new Date(DateUtil.formatDate(this.maxDate,'yyyy/MM/dd'))
        let maxDateTime = maxDate.getTime()
        let curMonthTime = new Date(this.selYear + '/' + (index+1) + '/01 00:00:00').getTime()
        if (curMonthTime > maxDateTime) {
          if(this.maxMsg && showMsg) this.$toast(this.maxMsg)
          return false
        }
      }
      if (this.minDate) {
        let minDate = new Date(DateUtil.formatDate(this.minDate,'yyyy/MM/dd'))
        let minDateTime = minDate.getTime()
        let curSelMonthLastDay = DateUtil.getStartAndEndDateByMonth([this.selYear,(index+1)]).endDate
        let curMonthTime = new Date(curSelMonthLastDay + ' 00:00:00').getTime()
        if (curMonthTime < minDateTime) {
          if(this.minMsg && showMsg) this.$toast(this.minMsg)
          return false
        }
      }
      return true
    }
  }
}
</script>

<style scoped lang="less">
//引入mixin和var
@import '../../../css/mixin.less';
.v-date-picker {
  justify-content: center;
  align-items: center;
  display: flex;
  background-color: #fff;
  &-droplist {
    // top: 0;
    // left: 0;
    // right: 0;
    // bottom: 0;
    background-color: rgba(0, 0, 0, 0.1);
    // position: fixed;
    width: 100%;
    // z-index: 2;
    &-header {
      background-color: #fff;
      position: relative;
      height: 36px;
      display: flex;
      font-size: 13px;
      background-color: #f7f7f7;
      .hairline(bottom, #eee);
    }
    &-yearhandler {
      display: flex;
      justify-content: center;
      align-items: center;
      margin-right: 10px;
    }
    &-monthhandler {
      flex: 1;
      white-space: nowrap;
      overflow-x: auto;
      overflow-y: hidden;
      -webkit-overflow-scrolling: touch;
      .month-item {
        width: 48px;
        display: inline-block;
        height: 36px;
        justify-content: center;
        line-height: 36px;
        color: #333;
        text-align: center;
        &.disabled {
          opacity: 0.4;
          &:active {
            color: #333;
          }
        }
        &:active {
          color: @color-primary;
        }
        &.active {
          color: @color-primary;
          font-weight: bold;
        }
      }
    }
    &-content {
      background-color: #fff;
      // padding-bottom: 15px;
    }
  }
  &-header {
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    &__label {
      font-size: 14px;
      display: flex;
      height: 100%;
      justify-content: center;
      align-items: center;
      &:active {
        opacity: 0.8;
      }
    }
    &__prev {
      transform: rotate(180deg);
    }
    &__prev,
    &__next {
      display: flex;
      width: 36px;
      height: 36px;
      justify-content: center;
      align-items: center;
      color: #999;
      font-size: 16px;
      &.disabled {
        opacity: 0.3;
      }
      &:active {
        background-color: #fafafa;
      }
    }
  }
}
.calendar-row {
  display: flex;
  &-header {
    border-bottom: solid 1px #f3f3f3;
    &:active {
      opacity: 1;
    }
    li {
      color: #aaa;
      font-weight: bold;
    }
  }
  li {
    flex: 1;
    display: flex;
    font-size: 11px;
    justify-content: center;
    align-items: center;
    height: 34px;
    &.day-cell {
      font-size: 12px;
    }
    &:active,&.active,&.selected{
      .date-num{
        width: 30px;
        height: 30px;
        background-color: @color-primary;
        color: #fff;
        border-radius: 200px;
        display: flex;
        justify-content: center;
        align-items: center;
        font-weight: bold;
      }
    }
    &.selected{
      .date-num{
        background-color:#bff4d3;
        color: @color-primary;
        font-weight: normal;
      }
    }
    &:active,&.active{
      .date-num{
        background-color: @color-primary;
        color: #fff;
        font-weight: bold;
      }
    }
    
    &.week-value {
      color: #999;
      border-right: solid 1px #f3f3f3;
    }
    &.disabled {
      opacity: 0.2;
    }
  }
}
</style>
